<?php

/**
 * 装饰器模式：通过把对象放到装饰器类中，动态改变一个对象的行为
 * Class Decorator
 */

interface Coffee 
{
    public function getCost();

    public function getDescription();
}

class SimpleCoffee implements Coffee
{
    public function getCost()
    {
        return 10;
    }

    public function getDescription()
    {
        return 'Simple coffee';
    }
}

// 装饰器
// 继承接口。然后再constructor中注入原始对象。并对其部分行为进行修改
class MilkCoffee implements Coffee
{
    protected $coffee;

    public function __construct(Coffee $coffee)
    {
        $this->coffee = $coffee;
    }

    public function getCost()
    {
        return $this->coffee->getCost() + 2;
    }

    public function getDescription()
    {
        return $this->coffee->getDescription() . ', milk';
    }
}

class WhipCoffee implements Coffee
{
    protected $coffee;

    public function __construct(Coffee $coffee)
    {
        return $this->coffee = $coffee;
    }

    public function getCost()
    {
        return $this->coffee->getCost() + 5;
    }

    public function getDescription()
    {
        return $this->coffee->getDescription() + ', whip';
    }
}


class VanillaCoffee implements Coffee
{
    protected $coffee;

    public function __construct(Coffee $coffee)
    {
        $this->coffee = $coffee;
    }

    public function getCost()
    {
        return $this->coffee->getCost() + 3;
    }

    public function getDescription()
    {
        return $this->coffee->getDescription() + ', vanilla';
    }
}

// usage
$simpleCoffee = new SimpleCoffee();
echo $simpleCoffee->getCost();
echo $simpleCoffee->getDescription();

$milkCoffee = new MilkCoffee($simpleCoffee);
echo $milkCoffee->getCost();
echo $milkCoffee->getDescription();